 /*
  * Mango CMS
  * Copyright 2008, Mango Web, and individual contributors as indicated
  * by the @authors tag. See the copyright.txt in the distribution for a
  * full listing of individual contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
package org.mangocms.seam.security;

import java.io.Serializable;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;
import org.mangocms.model.user.Group;
import org.mangocms.model.user.Role;
import org.mangocms.model.user.User;

/**
 * Seam authenticator class for Mango users
 * 
 * @author <a href="tanordheim@gmail.com">Trond Arve Nordheim</a>
 * @version $Revision: 1.1 $
 */
@Name("mangoAuthenticator")
@Install(precedence = Install.APPLICATION)
public class MangoAuthenticator implements Serializable {

	private static final long serialVersionUID = 1L;

	@Logger
	private Log logger;
	
	@In
	private Identity identity;
	
	@In
	private Credentials credentials;
	
	@In
	private EntityManager entityManager;
	
	/**
	 * Attempt to authenticate the current identity
	 * 
	 * @return true if the authentication was successful, false otherwise
	 */
	public boolean authenticate() {

		logger.debug("Authenticating user #0", credentials.getUsername());
		
		// Attempt to load the user with the specified username
		User user = null;
		try {
			user = (User) entityManager.createQuery("from User u where lower(u.username) = lower(:username)")
				.setParameter("username", credentials.getUsername())
				.getSingleResult();
		} catch (NoResultException e) {
			logger.error("User not found while authenticating: #0", credentials.getUsername());
			return false;
		}
		
		// Verify the input password
		if (user.isValidPassword(credentials.getPassword()) == false) {
			logger.error("Invalid password while authenticating for user: #0", credentials.getUsername());
			return false;
		}
		
		// Add all user roles to the identity
		for (Group group : user.getGroups()) {
			for (Role role : group.getRoles()) {
				identity.addRole(role.getName());
				logger.debug("Adding role #0 to identity for user #1", role.getName(), credentials.getUsername());
			}
		}
		
		return true;
		
	}

}
